/**
 *  Copyright Matt Silbernagel 2010
 *  
 *	This file is part of MobilePrinting.
 *
 *	MobilePrinting is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  MobilePrinting is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with MobilePrinting.  If not, see <http://www.gnu.org/licenses/>.
 */

package edu.uc.labs.MobilePrinting.GUI;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.xml.parsers.ParserConfigurationException;

import edu.uc.labs.MobilePrinting.Prefs.*;
import edu.uc.labs.MobilePrinting.OSUtils.SanityCheck;
import static edu.uc.labs.MobilePrinting.Configurator.*;

/**
 * @author Matt Silbernagel
 *
 */
@SuppressWarnings({ "unused" })
public class SetupPanel extends JPanel implements ActionListener {

	private static final long serialVersionUID = 6764508146474707542L;

	public static void createAndShowGUI(String windowTitle){
		UIManager.put("swing.boldMetal", Boolean.FALSE);
		SetupPanel s = new SetupPanel(windowTitle);
	}
	
	public SetupPanel(String frameTitle){
		UIManager.put("swing.boldMetal", Boolean.FALSE);
		this.frameTitle = frameTitle;
		 // Set System L&F
        try {
			UIManager.setLookAndFeel(
			    UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException e) {			
			e.printStackTrace();
		} catch (InstantiationException e) {			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		initComponents();

	}
	
	public boolean isDone(){
		return done;
	}
	
	public void initComponents(){
		
		// Setup the buttons
		nButton = new NextButton();
		bButton = new BackButton();
		cButton = new CancelButton();
		fButton = new FinishButton();
		nButton.addActionListener(this);
		bButton.addActionListener(this);
		cButton.addActionListener(this);
		fButton.addActionListener(this);
		
		// The Image
		icon = new ImageIcon(USERSPACE + ICONS + DELIM + IconArray.get("trayicon_norm"));
		
		descPanel = new DescriptionPanel();
		
		buttonPanel = new ButtonPanel();
		contentPanel = new ContentPanel();
		contentPanel.add(buttonPanel, BorderLayout.SOUTH);
		
		formPanel = new FormPanel(pageNumber);
		formPanel.add(formPanel.getServerPanel());
		
		contentPanel.add(formPanel, BorderLayout.CENTER);
		
		this.setLayout(new BorderLayout());
		this.add(descPanel, BorderLayout.NORTH);
		this.add(contentPanel, BorderLayout.SOUTH);
		
		mainFrame = new JFrame(frameTitle);
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container contentPane = mainFrame.getContentPane();
		contentPane.add(this);
		mainFrame.setLocation(400, 200);
		mainFrame.pack();
		mainFrame.setVisible(true);
	}
	
	public void setPageNumber(int number){
		this.pageNumber = number;
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		Command obj = (Command) e.getSource();
		obj.execute();	
	}
	
	public static void main(String[] args){
		SetupPanel p = new SetupPanel("Testing");
	}

	public JPanel descPanel;
	public JPanel contentPanel;
	public JPanel selectPanel;
	public JPanel buttonPanel;
	public FormPanel formPanel;
	public JFrame mainFrame;
	public NextButton nButton;
	public BackButton bButton;
	public CancelButton cButton;
	public FinishButton fButton;
	public ImageIcon icon;
	private int pageNumber = 1;
	private String frameTitle;
	public boolean done = false;
	
	// Variables that hold the values the user has set
	public String serverName = null;
	public String serverPort = null;
	public String startAtLogin = "0";
	public String deleteOnExit = "0";
	public String autoUpdate = "0";
	public String printerName = null;
	
	

	/**
	 * The class that implements the FormPanel
	 * This does most of the work for setting up 
	 * the user defaults
	 * @author Matt Silbernagel
	 */
	public class FormPanel extends JPanel{

		private static final long serialVersionUID = -151691919386174241L;
		public String currentPageNumber;
		public JTextField serverText;
		public JTextField portText;
		public JCheckBox startAtLoginCheckbox;
		public JCheckBox deleteOnExitCheckbox;
		public JCheckBox usageDataCheckbox;
		public JCheckBox autoUpdateCheckbox;
		public JTextField printerText;
		
		public FormPanel(int currentPageNumber){
			UIManager.put("swing.boldMetal", Boolean.FALSE);
			this.currentPageNumber = Integer.toString(currentPageNumber);
			setPreferredSize(new Dimension(400, 150));
		}
		
		/**
		 * Setup a panel that displays the server and port fields
		 * @return the panel that displays the textfields for server and
		 * ports
		 */
		public JPanel getServerPanel(){
			JPanel all = new JPanel();
			all.setLayout(new BoxLayout(all, BoxLayout.Y_AXIS));
			all.setPreferredSize(new Dimension(400, 80));
			
			// Setup all of the Panels
			JPanel server = new JPanel();
			JPanel serverDescPanel = new JPanel();
			JPanel port = new JPanel();
			JPanel portDescPanel = new JPanel();
			
			// Setup all of the labels and fonts
			JLabel serverLabel = new JLabel("<html>Server:</html>");
			JLabel portLabel = new JLabel("<html>Port:</html>");
			serverLabel.setPreferredSize(new Dimension(5, 11));
			portLabel.setPreferredSize(new Dimension(2, 11));
			JLabel serverDesc = new JLabel("<html>(Example: print.server.com)</html>");
			JLabel portDesc   = new JLabel("<html>(Example: 8080)</html>");
			serverDesc.setFont(new Font("Serif", Font.ITALIC, 11));
			portDesc.setFont(new Font("Serif", Font.ITALIC, 11));
			
			/*
			 *  Setup the text fields
			 *  If the user entered something then moves on
			 *  and later hits the back button make sure those 
			 *  values are redisplayed in the text fields
			 */
			serverText = new JTextField(15);
			if(serverName != null){
				serverText.setText(serverName);
			}
			portText = new JTextField(15);
			if(port != null){
				portText.setText(serverPort);
			}
			
			server.setPreferredSize(new Dimension(400, 5));
			server.setLayout(new BoxLayout(server, BoxLayout.X_AXIS));
			server.add(serverLabel);
			server.add(Box.createRigidArea(new Dimension(0,0)));
			server.add(serverText);
			
			port.setPreferredSize(new Dimension(400, 5));
			port.setLayout(new BoxLayout(port, BoxLayout.X_AXIS));
			port.add(portLabel);
			//port.add(Box.createRigidArea(new Dimension(20,0)));
			port.add(portText);
			
			// Setup the panel that holds the Description of the server field
			serverDescPanel.setLayout(new BoxLayout(serverDescPanel, BoxLayout.X_AXIS));
			serverDescPanel.add(Box.createRigidArea(new Dimension(115, 0)));
			serverDescPanel.add(serverDesc);
			
			// Setup the panel that holds the descripion of the port field
			portDescPanel.setLayout(new BoxLayout(portDescPanel, BoxLayout.X_AXIS));
			portDescPanel.add(Box.createRigidArea(new Dimension(115, 0)));
			portDescPanel.add(portDesc);

			all.add(server);
			all.add(serverDescPanel);
			all.add(Box.createRigidArea(new Dimension(0, 10)));
			all.add(port);
			all.add(portDescPanel);
			
			return all;
		}
		
		/**
		 * Setup the panel that displays multiple checkboxes
		 * @return the panel that displays checkboxes for basic user options
		 */
		public JPanel getOptionsPanel(){
			// The panel to return
			JPanel all = new JPanel();
			all.setLayout(new BoxLayout(all, BoxLayout.Y_AXIS));
			all.setPreferredSize(new Dimension(400, 120));
			
			// Setup all of the the labels 
			JLabel startAtLoginLabel = new JLabel("<html>Start MobliePrinting when the computer starts</html>");
			JLabel deleteOnExitLabel = new JLabel("<html>Delete Printer when the program exits</html>");
			JLabel autoUpdateLabel   = new JLabel("<html>Auto Update</html>");
			
			// Setup the checkboxes
			startAtLoginCheckbox = new JCheckBox();
			startAtLoginCheckbox.setSelected(SanityCheck.stringToBool(startAtLogin));
			deleteOnExitCheckbox = new JCheckBox();
			deleteOnExitCheckbox.setSelected(SanityCheck.stringToBool(deleteOnExit));
			autoUpdateCheckbox   = new JCheckBox();
			autoUpdateCheckbox.setSelected(SanityCheck.stringToBool(autoUpdate));
			autoUpdateCheckbox.setEnabled(false);
			
			// Setup the individual panels for each checkbox
			JPanel startPanel = new JPanel();
			startPanel.setLayout(new BoxLayout(startPanel, BoxLayout.X_AXIS));
			JPanel deletePanel = new JPanel();
			deletePanel.setLayout(new BoxLayout(deletePanel, BoxLayout.X_AXIS));
			JPanel autoPanel = new JPanel();
			autoPanel.setLayout(new BoxLayout(autoPanel, BoxLayout.X_AXIS));
			
			startPanel.add(startAtLoginLabel);
			startPanel.add(Box.createRigidArea(new Dimension(5,5)));
			startPanel.add(startAtLoginCheckbox);
			
			deletePanel.add(deleteOnExitLabel);
			deletePanel.add(Box.createRigidArea(new Dimension(5,5)));
			deletePanel.add(deleteOnExitCheckbox);
			
			autoPanel.add(autoUpdateLabel);
			autoPanel.add(Box.createRigidArea(new Dimension(5,5)));
			autoPanel.add(autoUpdateCheckbox);
			
			all.add(startPanel);
			all.add(Box.createRigidArea(new Dimension(0, 10)));
			all.add(deletePanel);
			all.add(Box.createRigidArea(new Dimension(0, 10)));
			all.add(autoPanel);
			
			return all;
		}
		
		/**
		 * Setup the panel that displays the naming textfield
		 * @return the panel that displays teh naming textfield
		 */
		public JPanel getNamingPanel(){
			JPanel all = new JPanel();
			all.setLayout(new BoxLayout(all, BoxLayout.Y_AXIS));
			all.setPreferredSize(new Dimension(400, 60));
			
			JPanel printerPanel = new JPanel();
			JPanel printerDescPanel = new JPanel();
			
			JLabel printerLabel = new JLabel("<html>Printer Name</html>");
			//printerLabel.setPreferredSize(new Dimension(5, 11));
			JLabel printerDescLabel = new JLabel("<html>The MobilePrinting Application will install and maintain " +
												 "one printer on your system. Please enter what you would like it to be " +
												 "called (exclude punctuation and spaces)");
			printerDescLabel.setFont(new Font("Serif",Font.PLAIN, 11));
			
			printerText = new JTextField(15);
			printerPanel.setLayout(new BoxLayout(printerPanel, BoxLayout.X_AXIS));
			printerPanel.setPreferredSize(new Dimension(400, 0));
			
			printerDescPanel.setLayout(new BoxLayout(printerDescPanel, BoxLayout.X_AXIS));
			printerDescPanel.add(printerDescLabel);
			
			printerPanel.add(printerLabel);
			printerPanel.add(Box.createRigidArea(new Dimension(0,0)));
			printerPanel.add(printerText);
			
			all.add(printerPanel);
			all.add(Box.createRigidArea(new Dimension(0,10)));
			all.add(printerDescPanel);
			return all;
		}
	}
	
	/**
	 * The class that implements the Description Panel
	 */
	public class DescriptionPanel extends JPanel {

		private static final long serialVersionUID = -5189505179833073767L;

		public DescriptionPanel() {
			UIManager.put("swing.boldMetal", Boolean.FALSE);
			setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
			setBorder(BorderFactory.createEmptyBorder(0, 25, 10, 25));
			setPreferredSize(new Dimension(450, 75));
			JLabel title = new JLabel("<html>MobilePrinting Setup</html>");
			JLabel description = new JLabel();
			JLabel iconLabel = new JLabel();
			iconLabel.setIcon(icon);
			JSeparator line = new JSeparator();
			description
					.setText("<html>This appears to be the first time that MobilePrinting has run. Please follow the "
							+ "on screen instructions to finish the one time initialization</html>");
			description.setFont(new Font("Serif", Font.ITALIC, 11));
			title.setFont(new Font("Serif", Font.BOLD, 14));
			
			JPanel iconPanel = new JPanel();
			iconPanel.setLayout(new BoxLayout(iconPanel, BoxLayout.X_AXIS));
			iconPanel.add(iconLabel);
			iconPanel.add(Box.createRigidArea(new Dimension(5,0)));
			iconPanel.add(title);
			iconPanel.setBackground(Color.WHITE);
			
			JPanel descPanel = new JPanel();
			descPanel.setLayout(new BoxLayout(descPanel, BoxLayout.X_AXIS));
			descPanel.add(description);
			descPanel.setBackground(Color.WHITE);
			
			add(Box.createRigidArea(new Dimension(0, 10)));
			add(iconPanel);
			add(line);
			add(Box.createRigidArea(new Dimension(0, 10)));
			add(descPanel);
			this.setBackground(Color.WHITE);
		}
	}
	
	/**
	 * The class that implements the Content Panel
	 * @author Matt Silbernagel
	 *
	 */
	public class ContentPanel extends JPanel {

		private static final long serialVersionUID = -6418774756291604065L;

		public ContentPanel(){
			UIManager.put("swing.boldMetal", Boolean.FALSE);
			this.setLayout(new BorderLayout());
		}
		
	}
	
	/**
	 * The class that implements the Button Panel
	 * @author Matt Silbernagel
	 *
	 */
	public class ButtonPanel extends JPanel {
		
		private static final long serialVersionUID = -8144888500037757237L;
		
		public ButtonPanel(){
			UIManager.put("swing.boldMetal", Boolean.FALSE);
			setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
			setPreferredSize(new Dimension(400, 35));
			setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
			add(Box.createHorizontalGlue());
			add(cButton);
			add(Box.createRigidArea(new Dimension(2, 0)));
			add(bButton);
			add(Box.createRigidArea(new Dimension(2, 0)));
			add(nButton);
			add(Box.createRigidArea(new Dimension(2, 0)));
			add(fButton);
		}
	}
	
	/**
	 * The class that implements the next button
	 * @author Matt Silbernagel
	 *
	 */
	public class NextButton extends JButton implements Command{

		private static final long serialVersionUID = 2186627651742311714L;
		private String currentPageNumber;

		/**
		 * Set up the next button
		 * @param currentPageNumber the page that we are currently viewing
		 */
		public NextButton(){
			UIManager.put("swing.boldMetal", Boolean.FALSE);
			this.setText("Next >>");
		}

		@Override
		public void execute() {
			this.currentPageNumber = Integer.toString(pageNumber);
			if(this.currentPageNumber.equalsIgnoreCase("1")){
				if(formPanel.serverText.getText().isEmpty() || formPanel.portText.getText().isEmpty()){
					JOptionPane.showMessageDialog(mainFrame, "You must enter a server AND a port");
				} else {
					serverName = formPanel.serverText.getText();
					serverPort = formPanel.portText.getText();
					// Reinitialize the panel and call the next page
					reInit();
					bButton.setEnabled(true);
				}
			}
			if(this.currentPageNumber.equalsIgnoreCase("2")){
				startAtLogin = boolToString(formPanel.startAtLoginCheckbox.isSelected());
				deleteOnExit = boolToString(formPanel.deleteOnExitCheckbox.isSelected());
				autoUpdate   = boolToString(formPanel.autoUpdateCheckbox.isSelected());
				// Reinitialze the panel and call the next page
				reInit();
			}
			
			
		}
		
		private void reInit(){
			pageNumber += 1;
			formPanel.remove(formPanel.getComponent(0));
			formPanel.validate();
			if(currentPageNumber.equalsIgnoreCase("1")){
				formPanel.add(formPanel.getOptionsPanel());
				formPanel.validate();
			}
			if(currentPageNumber.equalsIgnoreCase("2")){
				formPanel.add(formPanel.getNamingPanel());
				formPanel.validate();
				fButton.setEnabled(true);
				nButton.setEnabled(false);
			}
			
			formPanel.repaint();
			bButton.setEnabled(true);
		}
		
		private String boolToString( boolean b ){
			String num = b ? "1" : "0";
			return num;
		}
	
	}
	
	/**
	 * The class that implements the Back Button
	 * @author Matt Silbernagel
	 *
	 */
	public class BackButton extends JButton implements Command{

		private static final long serialVersionUID = -7804684868752911676L;
		private String currentPageNumber;
		
		/**
		 * Setup the BackButton
		 * @param currentPageNumber the page that we are currently viewing
		 */
		public BackButton(){
			UIManager.put("swing.boldMetal", Boolean.FALSE);
			this.setText("<< Back");
			this.currentPageNumber = Integer.toString(pageNumber);
			// If this is the first page, there is no need to 
			// show the back button
			if(this.currentPageNumber.equals("1")){
				this.setEnabled(false);
			}
		}
		
		@Override
		public void execute() {
			String cPageNumber = Integer.toString(pageNumber);
			if(cPageNumber.equalsIgnoreCase("2")){
				startAtLogin = boolToString(formPanel.startAtLoginCheckbox.isSelected());
				deleteOnExit = boolToString(formPanel.deleteOnExitCheckbox.isSelected());
				autoUpdate   = boolToString(formPanel.autoUpdateCheckbox.isSelected());
				JPanel s = formPanel.getServerPanel();
				formPanel.remove(formPanel.getComponent(0));
				formPanel.validate();
				formPanel.add(s);
				formPanel.validate();
				formPanel.repaint();
				pageNumber -= 1;
				this.setEnabled(false);
			}
			if(cPageNumber.equalsIgnoreCase("3")){
				JPanel s = formPanel.getOptionsPanel();
				formPanel.remove(formPanel.getComponent(0));
				formPanel.validate();
				fButton.setEnabled(false);
				nButton.setEnabled(true);
				formPanel.add(s);
				formPanel.validate();
				formPanel.repaint();
				pageNumber -= 1;
				
			}
		}
		
		private String boolToString( boolean b ){
			String num = b ? "1" : "0";
			return num;
		}
		
	}
	
	/**
	 * The class that implements the Cancel Button
	 * @author Matt Silbernagel
	 *
	 */
	public class CancelButton extends JButton implements Command{

		private static final long serialVersionUID = -3285235977058272040L;

		public CancelButton(){
			UIManager.put("swing.boldMetal", Boolean.FALSE);
			this.setText("Cancel");
		}
		
		@Override
		public void execute() {
			int isCancel = JOptionPane.showConfirmDialog(mainFrame, "Are you sure you want to cancel?\n This will stop the installation of MobilePrinting");
			String isCancelString = Integer.toString(isCancel);
			if (isCancelString.equalsIgnoreCase("0")){
				mainFrame.setVisible(false);
				mainFrame.dispose();
				return;
			}
		}
		
	}
	
	/**
	 * The class that implements the Finish Button
	 * @author Matt Silbernagel
	 *
	 */
	public class FinishButton extends JButton implements Command{

		private static final long serialVersionUID = -3879532547105198481L;
		private String currentPageNumber;
		
		public FinishButton(){
			UIManager.put("swing.boldMetal", Boolean.FALSE);
			this.setText("Finish");
			this.setEnabled(false);
		}
		
		@Override
		public void execute() {
			printerName = formPanel.printerText.getText();
			if(!SanityCheck.isPrinterNameValid(printerName)){
				// The name is not valid, let the user know
				JOptionPane.showMessageDialog(mainFrame, "Please don't use spaces or punctuation in the printer name ");
			} else {
				
				Preferences p = new Preferences();
				p.setPrinterName(printerName);
				p.setConfigServer(serverName + ":" + serverPort);
				p.setAutoUpdate(autoUpdate);
				p.setDeleteOnExit(deleteOnExit);
				p.setLogLevel("error");
				p.setStartAtLogin(startAtLogin);
				try {
					PreferencesWriter pw = new PreferencesWriter(p);
					pw.writeDefaults();
				} catch (ParserConfigurationException e) {
					LOGGER.error("Failed to initialize the preferenceswriter: " + e.toString());
				} catch (IOException e) {
					LOGGER.error("Unable to write default preferences...");
				}
				done = true;
				mainFrame.setVisible(false);
				mainFrame.dispose();
				return;
			}
			
		}

		
	}

}


